<?php

namespace thinkct\library;

use app\common\model\ai\app\Models as AppModel;
use app\common\model\ai\Group;
use app\common\model\ai\Message;
use app\common\model\ai\Message as MessageModel;
use app\admin\model\ai\Presets as presetsModel;
use app\common\model\ai\Models;
use thinkct\facade\ChatAI;
use app\common\facade\ai\UserVip;

class ChatData
{
    protected mixed $error;

    /**
     * 提交聊天内容
     */
    public function send_text($content, $group): array
    {
        $user_id = $group->user_id;
        $group_id = $group->id;
        // 获取模型
        $model = Models::where(['model' => $group->model, 'status' => 1])->find();
        if (!$model) {
            return [
                'status' => false,
                'type' => 'error',
                'content' => '当前模型已经下架，请切换模型',
            ];
        }
        //die(var_dump($model));
        // 获取模型key 随机
        $model_key = ChatAI::getModelKey($model->id);
        if (!$model_key) {
            return [
                'status' => false,
                'type' => 'error',
                'content' => '当前模型无可用的KEY，请切换模型',
            ];
        }
        $model->key = $model_key->key;
        $model->api_url = $model_key->api_url;

        // 判断是否为会员
        if (UserVip::isVip($user_id)) {
            UserVip::addRecord($user_id, 'chat', 1, '对话消费');
        } else {
            // ####扣除用户余额
            $user = \app\common\model\User::where('id', $user_id)->find();
            if ($user->money < $model_key->price) {
                return [
                    'status' => false,
                    'type' => 'error',
                    'content' => '余额不足，请充值',
                ];
            }

            $user->money = $user->money - $model_key->price;
            $user->save();
            $UserMoneyLog = \app\common\model\UserMoneyLog::create([
                'user_id' => $user_id,
                'money' => $model_key->price,
                'before' => $user->money + $model_key->price,
                'after' => $user->money,
                'memo' => '对话消费',
            ]);
            // ####结尾
        }


        // 违规检测
        if (!prohibited($content, $user_id)) {
            return [
                'status' => false,
                'type' => 'error',
                'content' => '你的内容包含违规词汇',
            ];
        }
        // 预算回复
        $presets = presetsModel::where('status', 1)->select();
        foreach ($presets as $value) {
            if(str_contains($content, $value->content)) {
                return [
                    'status' => true,
                    'type' => 'success',
                    'content' => $value->reply,
                ];
            }
        }
        // 关联上下文
        $messages = $this->context($group, $content);

        //die(var_dump($messages));

        // 发送消息
        $sendText = ChatAi::sendText($messages, '', $model);

        return [
            'status' => true,
            'type' => 'assistant',
            'content' => $sendText,
        ];
    }


    /**
     * 获取聊天内容
     */
    public function message_list(array $query): array
    {
        $messages = MessageModel::where($query)
            ->where('status', 1)
            ->select()
            ->toArray();
        // 遍历数据
        $message_list = [];
        foreach ($messages as $key => $value) {
            if (!empty($value['title'])) {
                $message_list[] = [
                    'id' => $value['id'],
                    'role' => 'user',
                    'content' => $value['title'],
                    'file' => \app\common\model\ai\MessageFile::where('message_id', $value['id'])->select()->toArray(),
                    'status' => !empty($value['title']) ? 1 : 0
                ];
            }
            if (!empty($value['content'])) {
                $message_list[] = [
                    'id' => $value['id'],
                    'role' => 'assistant',
                    'content' => $value['content'],
                    'file' => [],
                    'status' => !empty($value['content']) ?1 : 0
                ];
            }
        }
        return $message_list;
    }

    /**
     * 关联上下文
     */
    public static function context($group, $content): array
    {
        // 如果是gpt-4-vision-preview
        if ($group->model == 'gpt-4-vision-preview') {

            $file_list = request()->post('file_list');
            // 遍历数组格式
            $file_list = array_map(function ($value) {
                return [
                    'type' => 'image_url',
                    'image_url' => [
                        'url' => full_url($value['url'])
                    ]
                ];
            }, $file_list);

            return [
                [
                    "role" => "system",
                    "content" => [
                        [
                            'type' => 'text',
                            'text' => '请中文回复内容'
                        ]
                    ]
                ],
                [
                    'role' => 'user',
                    'content' => [
                        [
                            'type' => 'text',
                            'text' => $content
                        ],
                        ...$file_list
                    ]
                ]
            ];
        }
        // 如果是gpt-4-1106-vision-preview


        $restriction = input('restriction', $group->restriction);
        $message = Message::where(['user_id'=>$group->user_id, 'group_id'=>$group->id, 'status'=>1])
            ->limit($restriction)->select();
        $data = [
            ['role' => 'system', 'content' => $group->prompt]
        ];

        foreach ($message->toArray() as $value) {
            $data[] = [
                'role' => 'user',
                'content' => $value['title'],
            ];
            $data[] = [
                'role' => 'assistant',
                'content' => $value['content'],
            ];
        }
        $data[] = [
            'role' => 'user',
            'content' => $content,
        ];
        return $data;
    }


    // 创建组（全局默认）
    public function createGroup($title, $user_id, $app_id = 0)
    {
        // 创建组
        $group = new Group();
        // 获取默认模型应用
        $app = AppModel::where('is_default', 1);
        if($app_id) {
            $app = AppModel::where('id', $app_id);
        } else {
            $app = AppModel::where('is_default', 1);
        }
        $app = $app->find();
        //die(var_dump($app));
        if($app) {
            $group->app_id = $app->id;
            $group->name = $app->name;
            $group->cover = $app->cover;
            $group->prompt = $app->prompt;
        } else {
            // 默认应用
            $group->name = 'AI助手';
            $group->cover = \app\admin\model\ai\Config::where('name', 'ai_avatar')->value('value');
            $group->prompt = '你是一个智能机器人';
        }

        // 获取默认模型
        $model = Models::where('default', 1)->find();
        // 获取可用的模型key
        $model_key = ChatAI::getModelKey($model->id);

        if($model_key) {
            $group->model_id = $model->id;
            $group->model = $model->model;
            $group->restriction = $model_key->restriction;
            $group->max_reply_token = $model_key->max_reply_token;
        } else {
            // 默认模型
            $group->model = 'gpt-3.5-turbo';
            $group->restriction = 12;
            $group->max_reply_token = 2000;
        }
        //die(var_dump($group));
        // 写入数据
        $group->title = $title;
        $group->user_id = $user_id;
        $group->save();
        return $group;
    }

    // 获取错误
    public function getError()
    {
        return $this->error;
    }

    // event-stream返回数据
    public static function event_stream($content): void
    {
        header('Content-Type: text/event-stream');
        header('Connection: keep-alive');
        header('Cache-Control: no-cache');
        header('Access-Control-Allow-Origin: *');
        header('X-Accel-Buffering: no');

        echo 'data: '.json_encode(['time'=>date('Y-m-d H:i:s'), 'content'=>$content]).PHP_EOL.PHP_EOL;

        ob_flush();
        flush();
    }
}